package com.ecp.util;


import java.net.URLEncoder;
import java.nio.charset.CodingErrorAction;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.MessageConstraints;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

public class HttpClientUtil {
    private final static Logger logger = Logger.getLogger(HttpClientUtil.class);
    private final static int connectTimeout = 500000;
    private final static RequestConfig requestConfig = RequestConfig
            .custom()
            .setSocketTimeout(connectTimeout)
            .setConnectTimeout(connectTimeout)
            .setConnectionRequestTimeout(connectTimeout)
            .build();
    private static PoolingHttpClientConnectionManager connManager = null;
    private static CloseableHttpClient httpclient = null;

    static {
        try {
            SSLContext sslContext = SSLContexts.custom().useTLS().build();
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                }

                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                }
            }}, null);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
                    .<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", sslsf).build();
            connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            httpclient = HttpClients.custom().setConnectionManager(connManager).build();
            // Create socket configuration
            SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
            connManager.setDefaultSocketConfig(socketConfig);
            // Create message constraints
            MessageConstraints messageConstraints = MessageConstraints.custom()
                    .setMaxHeaderCount(200).setMaxLineLength(2000).build();
            // Create connection configuration
            ConnectionConfig connectionConfig = ConnectionConfig.custom()
                    .setMalformedInputAction(CodingErrorAction.IGNORE)
                    .setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8)
                    .setMessageConstraints(messageConstraints).build();
            connManager.setDefaultConnectionConfig(connectionConfig);
            connManager.setMaxTotal(200);
            connManager.setDefaultMaxPerRoute(20);
        } catch (KeyManagementException e) {
            logger.error("KeyManagementException", e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException", e);
        }
    }

    public static String invokeGet(String url, Map<String, String> params) throws Exception {
        String responseString = null;
        StringBuilder sb = new StringBuilder();
        sb.append(url);
        int i = 0;
        for (Entry<String, String> entry : params.entrySet()) {
            if (i == 0 && !url.contains("?")) {
                sb.append("?");
            } else {
                sb.append("&");
            }
            sb.append(entry.getKey());
            sb.append("=");
            String value = entry.getValue();
            sb.append(URLEncoder.encode(value, "UTF-8"));
            i++;
        }
        logger.info("[HttpUtils Get] begin invoke:" + sb.toString());
        HttpGet get = new HttpGet(sb.toString());
        get.setConfig(requestConfig);
        try {
            CloseableHttpResponse response = httpclient.execute(get);
            try {
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        responseString = EntityUtils.toString(entity, "UTF-8");
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            logger.info(String.format("[HttpUtils Get]Debug url:%s , response string %s:",
                    sb.toString(), responseString));
        } finally {
            get.releaseConnection();
        }
        return responseString;
    }

    public static String invokePost(String reqURL, Map<String, String> params, String encode) throws Exception {
        String responseContent = null;
        HttpPost httpPost = new HttpPost(reqURL);
        try {
            List<NameValuePair> parameters = new ArrayList<NameValuePair>();
            for (Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
            httpPost.setEntity(formEntity);
            httpPost.setConfig(requestConfig);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            StatusLine statusLine = null;
            try {
                // 执行POST请求
                statusLine = response.getStatusLine();
                if (statusLine != null && statusLine.getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity(); // 获取响应实体
                    try {
                        if (null != entity) {
                            responseContent = EntityUtils.toString(entity,encode);
                        }
                    } finally {
                        if (entity != null) {
                            entity.getContent().close();
                        }
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            logger.info(String.format("RequestURI : %s,StatusLine : %s", httpPost.getURI(),
                    statusLine.getStatusCode()));
        } finally {
            httpPost.releaseConnection();
        }
        return responseContent;
    }

    public static String invokePost(String reqURL, Map<String, String> params) throws Exception {
        String responseContent = null;
        HttpPost httpPost = new HttpPost(reqURL);
        try {
            List<NameValuePair> parameters = new ArrayList<NameValuePair>();
            for (Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            HttpEntity httpEntity = EntityBuilder.create().setParameters(parameters).build();
            httpPost.setEntity(httpEntity);
            httpPost.setConfig(requestConfig);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            StatusLine statusLine = null;
            try {
                // 执行POST请求
                statusLine = response.getStatusLine();
                if (statusLine != null && statusLine.getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity(); // 获取响应实体
                    try {
                        if (null != entity) {
                            responseContent = EntityUtils.toString(entity, Consts.UTF_8);
                        }
                    } finally {
                        if (entity != null) {
                            entity.getContent().close();
                        }
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            logger.info(String.format("RequestURI : %s,StatusLine : %s", httpPost.getURI(),
                    statusLine.getStatusCode()));
        } finally {
            httpPost.releaseConnection();
        }
        return responseContent;
    }

    public static String invokePost(String reqURL, String sendData, String encode) throws Exception {
        String responseContent = null;
        HttpPost httpPost = new HttpPost(reqURL);
        try {
            StringEntity stringEntity = null;
            if (StringUtils.isEmpty(encode)) {
                stringEntity = new StringEntity(sendData);
            } else {
                stringEntity = new StringEntity(sendData, encode);
            }
            httpPost.setEntity(stringEntity);
            httpPost.setConfig(requestConfig);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            StatusLine statusLine = null;
            try {
                // 执行POST请求
                statusLine = response.getStatusLine();
                if (statusLine != null && statusLine.getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity(); // 获取响应实体
                    try {
                        if (null != entity) {
                            responseContent = EntityUtils.toString(entity, Consts.UTF_8);
                        }
                    } finally {
                        if (entity != null) {
                            entity.getContent().close();
                        }
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            logger.info(String.format("RequestURI : %s,StatusLine : %s", httpPost.getURI(),
                    statusLine.getStatusCode()));
        } finally {
            httpPost.releaseConnection();
        }
        return responseContent;
    }

}
